package com.mcc.app.productionMat.task;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.api.R;
import com.mcc.app.cache.service.IPlcCacheService;
import com.mcc.app.group.domain.GroupSche;
import com.mcc.app.group.service.IGroupScheService;
import com.mcc.app.materials.domain.SinterMaterials;
import com.mcc.app.materials.service.ISinterMaterialsService;
import com.mcc.app.productionMat.domain.RawMaterialConsumption;
import com.mcc.app.productionMat.domain.RawMaterialCostAnalysis;
import com.mcc.app.productionMat.service.IRawMaterialConsumptionService;
import com.mcc.app.productionMat.service.IRawMaterialCostAnalysisService;
import com.mcc.common.core.text.Convert;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Slf4j
public class materialStatistics  implements CommandLineRunner {


    private int stockCount = 23;
    @Autowired
    private IPlcCacheService plcCacheService;

    @Autowired
    IRawMaterialConsumptionService rawMaterialConsumptionService;

    @Autowired
    private IGroupScheService groupScheService;

    @Autowired
    IRawMaterialCostAnalysisService rawMaterialCostAnalysisService;

    @Autowired
    ISinterMaterialsService sinterMaterialsService;


    @Override
    public void run(String... args) {

        generateReportDay();
        generateReportGroup();
        //        generateReportMonth();
//        generateReportYear();
    }


//已确认，夜里十二点准时更新当天的统计值,读取点位st2_dailyX_total的值
    @Scheduled(cron = "5 0 0 * * ?")
    private void generateReportDay() {
        try {

            calDayMaterial();


        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    private void calDayMaterial(){
        try{
            // 创建一个Calendar实例
            Calendar calendar = Calendar.getInstance();
            Date date = new Date();
            log.info("calDayMaterial ! current Date is "+date.toString());
            calendar.setTime(date);
            // 将日期向前推一天
            calendar.add(Calendar.DAY_OF_MONTH, -1);
            // 获取前一天的日期
            Date previousDate = calendar.getTime();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
            String formatStr = sdf.format(previousDate);
            Date formatDate = sdf.parse(formatStr);
            //读取各料仓是什么物料；

            String nameHeadString = "st2_ingredient";
            String nameTailString = "_name";
            //读取各料仓的当日物料累计值
            String dailyHeadString = "st2_previous";
            String dailyTailString = "_daily";
            Map<String,List<String>> nameDailyMap = new HashMap<>();//物料名 料仓列表  可能存在不同的料仓同样得物料名称
            for(int i = 1;i<=stockCount;i++){
                String nameString = nameHeadString +Integer.toString(i)+nameTailString;
                String materialName = Convert.toStr(plcCacheService.getRedisCache(nameString));//物料名称
                String dailyString  = dailyHeadString+Integer.toString(i)+dailyTailString;
//            materialMap.put("st2Daily"+i+"Total", materialName);
                if(nameDailyMap.containsKey(materialName)){
                    List<String> stockList = nameDailyMap.get(materialName);
                    stockList.add(dailyString);
                }else{
                    List<String> stockList = new ArrayList<>();
                    stockList.add(dailyString);
                    nameDailyMap.put(materialName, stockList);
                }
            }


            Double addDailyValue = 0.0;//当天物料累计消耗量
            Double addCost = 0.0;//当天成本累计消耗量

            for (Map.Entry<String, List<String>> entry : nameDailyMap.entrySet()){
                //首先对相同物料数据进行料仓数据合并
                List<String> stockList = entry.getValue();
                Double stockTotal = 0.0;
                for(int j = 0; j<stockList.size();j++){
                    String dailyIndex = stockList.get(j);
                    Double dailyValue = Convert.toDouble(plcCacheService.getRedisCache(dailyIndex), 0.0);//当日累计消耗 单位是？TODO
                    if(dailyValue != null){
                        stockTotal += Convert.toDouble(dailyValue, 0.0);
                        addDailyValue += Convert.toDouble(dailyValue, 0.0);

                    }
                }
                //计算消耗成本  根据物料名称从物料编码表中获取单价
                SinterMaterials sinterMaterials  = new SinterMaterials();
                sinterMaterials.setMaterialName(entry.getKey());
                SinterMaterials materials = sinterMaterialsService.selectSinterMaterialsByCode(sinterMaterials);
                Double price =materials != null? Convert.toDouble(materials.getPrice(), 0.0):0.0;//单位是？决定是否需要换算单位 TODO
                Double cost = price * stockTotal;//成本计算
                addCost += cost;
                RawMaterialConsumption rawMaterialConsumption = new RawMaterialConsumption();
                rawMaterialConsumption.setMatterName(entry.getKey());
                rawMaterialConsumption.setDateType(1);
                rawMaterialConsumption.setConsumption(stockTotal);
                rawMaterialConsumption.setConsumptionCost(cost);
                rawMaterialConsumption.setRawDate(formatDate);//需要核实清0 时刻计算的累积量算哪一天的？TODO
                RawMaterialConsumption existObj = rawMaterialConsumptionService.selectRawMaterialConsumptionByCond(rawMaterialConsumption);
                if (existObj == null) {
                    rawMaterialConsumptionService.insertRawMaterialConsumption(rawMaterialConsumption);
                } else {
                    rawMaterialConsumption.setId(existObj.getId());
                    rawMaterialConsumptionService.updateRawMaterialConsumption(rawMaterialConsumption);
                }

            }
            RawMaterialCostAnalysis rawMaterialCostAnalysis = new RawMaterialCostAnalysis();
            rawMaterialCostAnalysis.setRawDate(formatDate);
            rawMaterialCostAnalysis.setDateType(1);
            rawMaterialCostAnalysis.setConsumptionTotal(addDailyValue);
            rawMaterialCostAnalysis.setConsumptionCost(addCost);
            RawMaterialCostAnalysis existObj = rawMaterialCostAnalysisService.selectRawMaterialCostAnalysisByCond(rawMaterialCostAnalysis);
            if (existObj == null) {
                rawMaterialCostAnalysisService.insertRawMaterialCostAnalysis(rawMaterialCostAnalysis);
            } else {
                rawMaterialCostAnalysis.setId(existObj.getId());
                rawMaterialCostAnalysisService.updateRawMaterialCostAnalysis(rawMaterialCostAnalysis);
            }


        }catch (Exception e){
            log.info("exception is "+e.getMessage());
        }




    }

    //班组累计值一直等到下个循环班组来时才会重置
    @Scheduled(cron = "0 40 7/8 * * ?")
    private void generateReportGroup() {
        try {
            calGroupMaterialEx();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 班组数据从各个班次累计值点位中直接读取，各个班次数据直到下一次同样班次来时才会刷新
     */
    private void calGroupMaterialEx() {
        try{
            Date date = new Date();
            log.info("calGroupMaterialEx ! current date is "+date.toString());
            Date groupDate = DateUtil.offsetHour(date, -8);//为准确获取当前结束得是哪个班次
            GroupSche groupSche = groupScheService.getGroupScheByDt(groupDate);
            if (null == groupSche) {
                return;
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
            String formatStr = sdf.format(groupSche.getScheDate());
            Date formatDate = sdf.parse(formatStr);
            //读取各料仓是什么物料；
            String nameHeadString = "st2_ingredient";
            String nameTailString = "_name";
            //读取各料仓的当日物料累计值
            String headString = "";//夜班
            String tailString = "_total";
            if (groupSche.getClassesId() == 1)//夜班
            {
                headString = "st2_night";
            } else if (groupSche.getClassesId() == 2)//白板
            {
                headString = "st2_day";
            } else if (groupSche.getClassesId() == 3)//中班
            {
                headString = "st2_mid";
            }

            if (headString.isEmpty()) {
                log.info("The length of headString is 0 !");
                return;
            }
            Map<String, List<String>> nameDailyMap = new HashMap<>();//物料名 料仓列表  可能存在不同的料仓同样得物料名称
            for (int i = 1; i <= stockCount; i++) {
                String nameString = nameHeadString + Integer.toString(i) + nameTailString;
                String materialName = Convert.toStr(plcCacheService.getRedisCache(nameString));//物料名称
                String dailyString = headString + Integer.toString(i) + tailString;
//            materialMap.put("st2Daily"+i+"Total", materialName);
                if (nameDailyMap.containsKey(materialName)) {
                    List<String> stockList = nameDailyMap.get(materialName);
                    stockList.add(dailyString);
                } else {
                    List<String> stockList = new ArrayList<>();
                    stockList.add(dailyString);
                    nameDailyMap.put(materialName, stockList);
                }
            }
            Double adDailyValue = 0.0;//班组得累计量
            Double addCost = 0.0;//班组得累计量
            for (Map.Entry<String, List<String>> entry : nameDailyMap.entrySet()) {
                //首先对相同物料数据进行料仓数据合并
                SinterMaterials sinterMaterials = new SinterMaterials();
                sinterMaterials.setMaterialName(entry.getKey());
                SinterMaterials materials = sinterMaterialsService.selectSinterMaterialsByCode(sinterMaterials);
                Double price = materials != null ? Convert.toDouble(materials.getPrice(), 0.0) : 0.0;//单位是？决定是否需要换算单位 TODO
                List<String> stockList = entry.getValue();

                Double stockTotal = 0.0;
                for (int j = 0; j < stockList.size(); j++) {

                    String dailyIndex = stockList.get(j);
                    //该班组开始时得各物料值
                    Double dailyValue = Convert.toDouble(plcCacheService.getRedisCache(dailyIndex), 0.0);//当日累计消耗 单位是？TODO

                    stockTotal += dailyValue;

                }
                Double cost = price * stockTotal;//成本计算
                adDailyValue += stockTotal;

                addCost += cost;
                RawMaterialConsumption rawMaterialConsumption = new RawMaterialConsumption();
                rawMaterialConsumption.setMatterName(entry.getKey());
                rawMaterialConsumption.setDateType(0);

                rawMaterialConsumption.setConsumption(stockTotal);
                rawMaterialConsumption.setConsumptionCost(cost);
                rawMaterialConsumption.setRawDate(formatDate);//需要核实清0 时刻计算的累积量算哪一天的？排班日期和实际日期应该是一致得；TODO
                rawMaterialConsumption.setClassesName(groupSche.getClassesName());
                rawMaterialConsumption.setTeamName(groupSche.getTeamName());
                RawMaterialConsumption existObj = rawMaterialConsumptionService.selectRawMaterialConsumptionByCond(rawMaterialConsumption);
                if (existObj == null) {
                    rawMaterialConsumptionService.insertRawMaterialConsumption(rawMaterialConsumption);
                } else {
                    rawMaterialConsumption.setId(existObj.getId());
                    rawMaterialConsumptionService.updateRawMaterialConsumption(rawMaterialConsumption);
                }
            }
            RawMaterialCostAnalysis rawMaterialCostAnalysis = new RawMaterialCostAnalysis();
            rawMaterialCostAnalysis.setRawDate(formatDate);//需要核实清0 时刻计算的累积量算哪一天的？排班日期和实际日期应该是一致得；TODO
            rawMaterialCostAnalysis.setClassesName(groupSche.getClassesName());
            rawMaterialCostAnalysis.setTeamName(groupSche.getTeamName());
            rawMaterialCostAnalysis.setDateType(0);
            rawMaterialCostAnalysis.setConsumptionTotal(adDailyValue);
            rawMaterialCostAnalysis.setConsumptionCost(addCost);
            RawMaterialCostAnalysis existObj = rawMaterialCostAnalysisService.selectRawMaterialCostAnalysisByCond(rawMaterialCostAnalysis);
            if (existObj == null) {
                rawMaterialCostAnalysisService.insertRawMaterialCostAnalysis(rawMaterialCostAnalysis);
            } else {
                rawMaterialCostAnalysis.setId(existObj.getId());
                rawMaterialCostAnalysisService.updateRawMaterialCostAnalysis(rawMaterialCostAnalysis);
            }
        }catch (Exception e){
            log.info("exception is "+e);
        }

    }




    }